import cx_Oracle
import json
import http.client
import os
from datetime import *
from time import sleep
from time import clock
from multiprocessing import Process
from timeit import timeit
from threading import Timer

# 数据库配置
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8'
TOKEN = 'buptcampuscard'
ORACLE_URL = 'lzc/123456@10.3.55.52/ywkdb'
TARGET_URL = '111.231.68.175'

# 最长数据流发送长度
MAX_LEN = 1000000

# 最长发送时间
TIME_OUT_SEC = 7


# json日期编码默认形式
class JsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, obj)


# 发送json数据流
def post(url, js_str):
    conn = http.client.HTTPConnection(TARGET_URL)
    conn.request(method='POST', url=url, body=js_str)
    response = conn.getresponse()
    try:
        sub_time = float(json.loads(response.read())['time'])
    except:
        sub_time = 0.1
    conn.close()
    return response.status, response.reason, sub_time


def js_package(list, init):
    R = []
    js = {}
    for each in list:
        R.append(dict(zip(init['KEY'], each)))
        js = {init['TABLE_NAME']: R, 'TOKEN': TOKEN}
    return json.dumps(js, cls=JsonEncoder)


# json数据流分片发送
def js_list(url, SQL, init):
    conn = cx_Oracle.connect(ORACLE_URL)
    cursor = conn.cursor()
    cursor.execute(SQL)
    sub_time = post(url, js_package(cursor.fetchmany(1), init))[2]
    print('每条数据发送时间:' + str(sub_time) + '秒')
    max = int(TIME_OUT_SEC / sub_time)
    print('每次最多发送' + str(max) + '条数据')
    print('发送数据...')
    data = cursor.fetchall()
    total = int(len(data) / max)
    flag = 0
    while True:
        re = data[flag * max:(flag + 1) * max]
        if len(re) == 0:
            break
        print(str(post(url=url, js_str=js_package(re, init))) + '[%d / %d]' % (flag + 1, total + 1))
        flag += 1
    cursor.close()
    conn.close()

    return 0


# 获取配置信息
def get_response(url):
    conn = http.client.HTTPConnection(TARGET_URL)
    conn.request(method='GET', url=url)
    response = conn.getresponse()
    latest_id = response.read().decode('utf-8')
    conn.close()
    return response.status, latest_id


def syn_course():
    SQL = 'SELECT DISTINCT COURSE_CODE,COURSE_NAME FROM YDZC.VIEW_STUDENT_GRADE  ORDER BY COURSE_CODE'
    js_init = {
        'TABLE_NAME': 'COURSE_INFO',
        'KEY': ['COURSE_ID', 'COURSE_NAME']
    }
    url = '/syn/course/'
    print('正在从本地库获取课程数据.......')
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_student():
    SQL = "SELECT STUDENT_NO,STUDENT_NAME FROM YDZC.VIEW_STUDENT_BASICINFO WHERE IS_IN_SCHOOL='1'"
    js_init = {
        'TABLE_NAME': 'STUDENT_INFO',
        'KEY': ['STUDENT_ID', 'STUDENT_NAME']
    }
    url = '/syn/student/'
    print('正在从本地库获取学生数据.......')
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_news():
    SQL = "SELECT * FROM YDZC.VIEW_NEWS WHERE NEWS_PUB_DATE >= SYSDATE - 90"
    js_init = {
        'TABLE_NAME': 'NEWS',
        'KEY': ['NEWS_ID',
                'NEWS_TITLE',
                'NEWS_AUTHOR',
                'NEWS_CATEGORY',
                'NEWS_PUB_DATE',
                'NEWS_CONTENT',
                ]
    }
    print('正在从本地库获取新闻数据.......')
    url = '/syn/news/'
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_book():
    SQL = "SELECT * FROM YDZC.VIEW_BOOK_SEARCH"
    js_init = {
        'TABLE_NAME': 'BOOK_INFO',
        'KEY': ['name',
                'isbn',
                'id',
                'author',
                'publish',
                'index',
                ]
    }
    print('正在从本地库获取图书信息数据.......')
    url = '/syn/book/'
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_save():
    SQL = "SELECT OUTID,OPDT,DSCRP,OPFARE,ODDFARE,ID " \
          "FROM YDZC.V_YKT_SAVE JOIN YDZC.VIEW_STUDENT_BASICINFO " \
          "ON OUTID = STUDENT_NO " \
          "WHERE IS_IN_SCHOOL = '1' AND OPDT > SYSDATE - 120 " \
          "ORDER BY ID"
    js_init = {
        'TABLE_NAME': 'SAVE_RECORD',
        'KEY': ['student_id',
                'datetime',
                'way',
                'amount',
                'balance',
                'id',
                ]
    }
    url = '/syn/ecard_record/'
    print('正在从本地库获取一卡通圈存数据.......')
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_consume():
    SQL = "SELECT OUTID,OPDT,DSCRP,OPFARE,ODDFARE,ID " \
          "FROM YDZC.V_YKT_CONSUME JOIN YDZC.VIEW_STUDENT_BASICINFO " \
          "ON OUTID = STUDENT_NO " \
          "WHERE IS_IN_SCHOOL = '1' AND OPDT > SYSDATE - 120 " \
          "ORDER BY ID"
    js_init = {
        'TABLE_NAME': 'CONSUME_RECORD',
        'KEY': ['student_id',
                'datetime',
                'way',
                'amount',
                'balance',
                'id',
                ]
    }
    url = '/syn/ecard_record/'
    print('正在从本地库获取一卡通消费数据.......')
    js_list(url, SQL, js_init)
    return '同步完成'


def syn_book_lend():
    print('准备删除已有数据')
    url = '/syn/del/?TOKEN=buptcampuscard&KEY=book_lend'
    response = get_response(url)
    if response[0] == 200:
        print(response[1])
        SQL = "SELECT LEND_TIME,LEND_DEADLINE,BOOK_NAME,READER_ID " \
              "FROM YDZC.VIEW_BOOK_LEND JOIN YDZC.VIEW_STUDENT_BASICINFO " \
              "ON STUDENT_NO = READER_ID " \
              "WHERE IS_IN_SCHOOL = '1'"
        js_init = {
            'TABLE_NAME': 'BOOK_LEND',
            'KEY': ['lend_time',
                    'lend_deadline',
                    'book_name',
                    'student_id',
                    ]
        }
        url = '/syn/book_lend/'
        print('正在从本地库获取借书数据.......')
        js_list(url, SQL, js_init)
        return '同步完成'
    else:
        return response


def syn_course_selection():
    print('准备删除已有数据')
    url = '/syn/del/?TOKEN=buptcampuscard&KEY=course_selection'
    response = get_response(url)
    if response[0] == 200:
        print(response[1])
        SQL = "SELECT COURSE_CODE,ID,YEAR,TERM,GRADE " \
              "FROM YDZC.VIEW_STUDENT_GRADE JOIN YDZC.VIEW_STUDENT_BASICINFO " \
              "ON ID = STUDENT_NO " \
              "WHERE IS_IN_SCHOOL = '1'"
        js_init = {
            'TABLE_NAME': 'COURSE_SELECTION',
            'KEY': ['course_id',
                    'student_id',
                    'year',
                    'term',
                    'grade',
                    ]
        }
        url = '/syn/course_selection/'
        print('正在从本地库获取学生成绩数据.......')
        js_list(url, SQL, js_init)
        return '同步完成'
    else:
        return response


def new_info():
    url_save_record = '/syn/getlatest/?TOKEN=buptcampuscard&KEY=save_record'
    response = get_response(url_save_record)
    if response[0] == 200:
        print('获取数据成功，最后一次更新的数据圈存数据ID为：' + response[1])
        SQL = "SELECT OUTID,OPDT,DSCRP,OPFARE,ODDFARE,ID " \
              "FROM YDZC.V_YKT_SAVE JOIN YDZC.VIEW_STUDENT_BASICINFO " \
              "ON OUTID = STUDENT_NO " \
              "WHERE IS_IN_SCHOOL = '1' AND ID > %s ORDER BY ID" % response[1]
        js_init = {
            'TABLE_NAME': 'SAVE_RECORD',
            'KEY': ['student_id',
                    'datetime',
                    'way',
                    'amount',
                    'balance',
                    'id',
                    ]
        }
        url = '/syn/ecard_record/'
        print('更新一卡通圈存数据.......')
        js_list(url, SQL, js_init)
    else:
        print('获取数据失败:' + str(response[0]))
    url_consume_record = '/syn/getlatest/?TOKEN=buptcampuscard&KEY=consume_record'
    response = get_response(url_consume_record)
    if response[0] == 200:
        print('获取数据成功，最后一次更新的数据消费数据ID为：' + response[1])
        SQL = "SELECT OUTID,OPDT,DSCRP,OPFARE,ODDFARE,ID " \
              "FROM YDZC.V_YKT_CONSUME JOIN YDZC.VIEW_STUDENT_BASICINFO " \
              "ON OUTID = STUDENT_NO " \
              "WHERE IS_IN_SCHOOL = '1' AND ID > %s ORDER BY ID" % response[1]
        js_init = {
            'TABLE_NAME': 'CONSUME_RECORD',
            'KEY': ['student_id',
                    'datetime',
                    'way',
                    'amount',
                    'balance',
                    'id',
                    ]
        }
        url = '/syn/ecard_record/'
        print('更新一卡通消费数据.......')
        js_list(url, SQL, js_init)
    else:
        print('获取数据失败:' + str(response[0]))
    return '同步完成'


def syn_auto():
    cur_day = datetime.now().day
    while True:
        try:
            if cur_day != datetime.now().day:
                syn_book_lend()
                cur_day = datetime.now().day
            new_info()
            sleep(100)
        except:
            continue


# if __name__ == '__main__':
#     print('开始同步基础信息')
#     process1 = Process(target=syn_student)
#     process2 = Process(target=syn_book)
#     process3 = Process(target=syn_course)
#     process1.start()
#     process2.start()
#     process3.start()
#     process1.join()
#     process3.join()
#     print('开始同步课程选择信息')
#     process4 = Process(target=syn_course_selection())
#     process4.start()
#     process2.join()
#     print('开始同步图书借阅信息')
#     process5 = Process(target=syn_book_lend())
#     process5.start()

if __name__ == '__main__':
    syn_auto()
